package boot;

import POJO.People;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import workflow.Data;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

@SpringBootApplication(scanBasePackages = {"controller", "config", "service", "task"})
//@EnableAutoConfiguration

//@ComponentScan(basePackages = {"controller","config","service"})
@MapperScan("mapper")
public class Application {
    public static void main(String[] args) {
        //返回IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        //查看容器里的组件
        /*String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String name : beanDefinitionNames)
            System.out.println(name);*/

//        //从容器中获取组件
//        People xiaoMing1 = run.getBean("xiaoMing", People.class);
//        People xiaoMing2 = run.getBean("xiaoMing", People.class);
//        System.out.println("是否同一个实例：" + (xiaoMing1 == xiaoMing2));
//
//        myConfig bean = run.getBean(myConfig.class);//获取代理对象 首先会在容器里找对象，没有才生成
//        People xiaoMing3 = bean.xiaoMing();
//        People xiaoMing4 = bean.xiaoMing();
//        System.out.println(xiaoMing3 == xiaoMing2);
//
//        System.out.println("-----------------");
        String[] names = run.getBeanNamesForType(People.class);
        for (String n : names){
            System.out.println(n);
            People bean = (People) run.getBean(n);
            System.out.println(bean);
        }


//        boolean b = run.containsBean("xiaoMei");
//        System.out.println(b);

        //学习工作流
        try {
            studyWorkFlow(run);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 学习工作流
     *
     * @author 朱序豪
     * @date 2023/2/5 14:54
     */
    private static void studyWorkFlow(ConfigurableApplicationContext run) throws IOException {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//生成 activiti的数据库表
        RepositoryService repositoryService = processEngine.getRepositoryService();
        TaskService taskService = processEngine.getTaskService();
        HistoryService historyService = processEngine.getHistoryService();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //1、部署流程
//        deploy_test(repositoryService);

        //2、启动流程实例 根据流程定义的key启动
//        startWorkFlow_test(processEngine);

        //3、查询个人待执行的任务
//        String taskId = queryWorkFlow_task(taskService);

        //4、完成任务by任务id
//        taskService.complete(taskId);

        //1、1使用压缩包部署流程（压缩包里包含多个bpmn 和 png）
//        deployByZIP_test(run, repositoryService);

        //5、删除流程部署信息  需结束所有流程实例
//        deleteDeployment(repositoryService);

        //6、下载流程资源文件 bpmn、png
//        downloadResource(repositoryService);

        //7、挂起、激活
//        suspendOrActivate(repositoryService);

        //8、UEL表达式
//        study_UEL(repositoryService, runtimeService);

        //9、监听器
//        BusinessTripListener idea里无法设置taskLinster todo

        //10、流程变量
//        test_workflow_variables(repositoryService, runtimeService, taskService);

        //11、组任务 todo

        //12、网关 todo
    }

    private static void test_workflow_variables(RepositoryService repositoryService, RuntimeService runtimeService, TaskService taskService) {
        //部署
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("bpmn/businessTrip-流程变量.bpmn20.xml")
                .name("测试流程变量")
                .deploy();
        System.out.println("部署name：" + deploy.getName());
        System.out.println("部署id：" + deploy.getId());
        //启动
        Map<String, Object> map = new HashMap<>();
        map.put("creator", "金刚狼");
        map.put("boss", "朱老板1");
        map.put("cai_wu", "朱财务1");
        Data data = new Data();
        data.setDays(3);
        map.put("data", data);
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("businessTrip-variables", map);
        System.err.println("10、流程定义ID：" + instance.getProcessDefinitionId());
        System.err.println("10、流程实例ID：" + instance.getId());
        System.err.println("10、当前活动ID：" + instance.getActivityId());
        //完成任务 测试流向
        Task task = taskService.createTaskQuery().taskAssignee("金刚狼").processDefinitionKey("businessTrip-variables").singleResult();
        taskService.complete(task.getId());
    }

    private static void study_UEL(RepositoryService repositoryService, RuntimeService runtimeService) {
        //部署
        Deployment deploy = repositoryService.createDeployment()
                .name("出差流程-UEL")
                .addClasspathResource("bpmn/businessTrip-UEL.bpmn20.xml")
                .deploy();
        System.out.println("部署name：" + deploy.getName());
        System.out.println("部署id：" + deploy.getId());
        //启动
        Map<String, Object> map = new HashMap<>();
        map.put("creater", "坏猪");
        map.put("leader", "朱领导");
        map.put("boss", "朱老板");
        map.put("cai_wu", "朱财务");
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("businessTrip-UEL", "业务id_002", map);
        System.err.println("8、流程定义ID：" + instance.getProcessDefinitionId());
        System.err.println("8、流程实例ID：" + instance.getId());
        System.err.println("8、当前活动ID：" + instance.getActivityId());
        System.err.println("8、业务key：" + instance.getBusinessKey());
    }

    private static void suspendOrActivate(RepositoryService repositoryService) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("businessTrip").singleResult();
        if (processDefinition.isSuspended()) {
            //激活 流程定义 及其 流程实例
            repositoryService.activateProcessDefinitionByKey("businessTrip", true, null);//日期为null时 立即挂起、激活
        } else {
            //挂起 流程定义 及其 流程实例
            repositoryService.suspendProcessDefinitionByKey("businessTrip", true, null);
        }
    }

    private static void downloadResource(RepositoryService repositoryService) throws IOException {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("businessTrip")
                .singleResult();
        InputStream bpmnInput = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
        InputStream pngInput = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getDiagramResourceName());
        File bpmnFile = new File("D:/study_workflow/businessTrip.bpmn");
        File pngFile = new File("D:/study_workflow/businessTrip.png");
        FileOutputStream bpmnOutput = new FileOutputStream(bpmnFile);
        IOUtils.copy(bpmnInput, bpmnOutput);
        FileOutputStream pngOutput = new FileOutputStream(pngFile);
        IOUtils.copy(pngInput, pngOutput);
        bpmnInput.close();
        pngInput.close();
        bpmnOutput.close();
        pngOutput.close();
    }

    private static void deleteDeployment(RepositoryService repositoryService) {
        List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery().processDefinitionKey("businessTrip").list();
        for (ProcessDefinition definition : definitionList) {
            System.err.println("5、部署id:" + definition.getDeploymentId());

        }
//        repositoryService.deleteDeployment(definition.getDeploymentId());
        repositoryService.deleteDeployment("ad0cc331-a7b4-11ed-8a48-e4e74948c4eb");
    }

    private static void deployByZIP_test(ConfigurableApplicationContext run, RepositoryService repositoryService) {
        InputStream inputStream = null;
        try {
            //fileInputStream = new FileInputStream("D:\\my_project\\hello-spring-boot\\src\\main\\resources\\bpmn\\businessTrip.rar");
            inputStream = run.getClassLoader().getResourceAsStream("bpmn/businessTrip.rar");
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (null == inputStream) return;
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        Deployment deploy = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();
        System.out.println("流程部署ID：" + deploy.getId());
        System.out.println("流程部署名称：" + deploy.getName());
    }

    private static String queryWorkFlow_task(TaskService taskService) {
        List<Task> tasks = taskService.createTaskQuery()
                .processDefinitionKey("businessTrip")//流程定义中的key
                .taskAssignee("badpig")//负责人
                .list();
        tasks.forEach(task -> {
            System.err.println("3、流程实例ID：" + task.getProcessInstanceId());
            System.err.println("3、任务ID：" + task.getId());
            System.err.println("3、任务负责人：" + task.getAssignee());
            System.err.println("3、任务名称：" + task.getName());
        });
        return tasks.get(0).getId();
    }

    private static void startWorkFlow_test(ProcessEngine processEngine) {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("businessTrip", "业务id_001");
        System.err.println("2、流程定义ID：" + instance.getProcessDefinitionId());
        System.err.println("2、流程实例ID：" + instance.getId());
        System.err.println("2、当前活动ID：" + instance.getActivityId());
        System.err.println("2、业务key：" + instance.getBusinessKey());
    }

    private static void deploy_test(RepositoryService repositoryService) {
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请流程-1")
                .addClasspathResource("bpmn/businessTrip.bpmn20.xml")
                .addClasspathResource("bpmn/businessTrip.png")
                .disableSchemaValidation()//禁止校验文件
                .deploy();//部署流程
        System.err.println(deploy.getName() + "----" + deploy.getId() + "----" + deploy.getDeploymentTime() + "-----------------------");
    }
}

